#-*-coding:utf-8-*-
from fileoperate import FileOperate
from newtest import newtest
'''
This module is used to compress the Image.
'''
class MatrixBytesCompress:
    '''
    This class will comstruct a Matrix in the memory to remenber the location of the bytes and save the location in a relative small memory by use div.
    In this program,the \x00\x00,\x00\x01,\x00\x02 are used for special function.
    \x00\x00 is used for endblock
    '''
    def __init__(self,rows = 256,cols = 256, width = 256):
        '''
        to build the Matrix and init it by zeros.
        '''
        self.content = [[[0 for i in range(width)]for j in range(cols)]for k in range(rows)]        #to save the datas.
        self.contentextra = ''      #to save the bytes in the end which can't find other bytes to ensure it in the matrix,if will contain 2 element in total
        self.fileModule = FileOperate()         #to operate the files
        self.width = width
        self.cols = cols
        self.rows = rows
        self.datalength = 0         #to record the data length.

    def GetDataByPos(self,row,col,width):
        '''
        Get the data by Pos
        '''
        if self.content:
            return self.content[row][col][width]
        return None

    def AddBytes(self,In,loc):
        '''
        Add Bytes in the Matrix!
        '''
        locpos = GetMatrixPosStr(loc)   #Get the location str and pos
        locstr = GetMatrixLoc(In)
        if self.content:
            if self.content[locstr[0]][locstr[1]][locstr[2]] == 0:  #repressent it is the first one
                self.content[locstr[0]][locstr[1]][locstr[2]] == locstr
            else:
                self.content[locstr[0]][locstr[1]][locstr[2]].append(locstr)
            self.datalength += 1
            return True
        else:
            return False

    def GetMatrixLoc(self,In):
        '''
        Get the location in the Matrix.
        '''
        k = [ord(In[0]),ord(In[1]),ord(In[2])]
        return k

    def GetMatrixPosStr(self,loc):
        '''
        Convert the intorder into Matrix str order.
        '''
        if loc >= 65535:
            return False
        else:
            loc += 4
            k1 = chr(loc / 256)
            k2 = chr(loc % 256)
            return k1 + k2

    def GetIntPos(self,loc):
        '''
        Convert the string location into real int location.
        '''
        s = ord(loc[0]) * 256 + ord(loc[1]) - 4
        return s

    def GetDatalength(self,mode = 0):
        '''
        return the the length of the data,if the mode == 0 return self.datalength,if mode == 1 restatistics it
        '''
        if mode == 0:
            return self.datalength
        elif mode == 1:
            ktotal = 0      #to record the total element
            ktotal += len(self.contentextra)        #the end element of the data text
            for i in range(self.rows):
                for j in range(self.cols):
                    for k in range(self.width):
                        if self.content[i][j][k] != 0:
                            ktotal += len(self.content[i][j][k])        #one pos sometime contain more
            return ktotal

        else:
            return False            #error control code

    def GetDataStr(self):
        '''
        This function will convert the MatrixData into string so that it will save in file more conviniently!
        '''
        if self.content:
            datastr = ''
            datastr = datastr +self.contentextra + '\x00\x02\x00\x01'           #append the end bytes into the datastr.
            #deal with the big Matrix Data
            for i in range(self.rows):
                for j in range(self.cols):
                    for k in range(self.width):
                        if self.content[i][j][k] == 0:
                            datastr += '\x00\x01'
                        else:
                            klent = len(self.content[i][j][k])
                            for l in range(klent):
                                datastr += self.content[i][j][k][l]
                                if l != klent - 1:      #not the last element
                                    #datastr += ' '
                                #else:
                                    datastr += '\x00\x01'
                    datastr += '\x00\x02'
                datastr += '\x00\x03'
            datastr += '\x00\x00'           #different strings will differ from each other by '\r\n'
            return datastr
        else:
            return ''

    def ConstructMartixByStr(self,datastr):
        '''
        This will allow the programme construct the Matrix by saved buffer.
        '''
        if datastr[-2:] != '\x00\x00':
            return False        # a simple and easy inspect behavior
        else:
            cpos = 0 #to record current reading point
            kpos = datastr.finde('\x00\x02\x00\x01')
            #The extra string in the end of the original string
            if kpos == -1:
                return False
            else:
                self.contentextra = datastr[cpos:kpos]
                cpos = kpos + 4 #set the reading point
            ntotal = len(datastr)   #Get the total string
            i,j,k,np = [0,0,0,0]    #initial the step,np refer to the next character.
            while (cpos < ntotal): #begin to read
                flag = datastr[cpos]    #to judge the next symbol
                if flag == '\x00':
                    flag2 = datastr[cpos + 1]
                    if flag2 == '\x01':
                        k += 1
                        if k == self.width:
                            k = 0
                        cpos += 2
                        continue
                    elif flag2 == '\x02':
                        j += 1
                        if j == self.cols:
                            j = 0
                        cpos += 2
                        continue
                    elif flag2 == '\x03':
                        i += 1
                        cpos += 2
                        continue
                    elif flag2 == '\x00':
                        break           #the end of the block
                    else:
                        if self.content[i][j][k] == 0:
                            self.content[i][j][k] = [datastr[cpos:(cpos + 2)]]
                        else:
                            self.content[i][j][k].append(datastr[cpos:(cpos + 2)])
                        cpos += 2
                else:
                    if self.content[i][j][k] == 0:
                        self.content[i][j][k] = [datastr[cpos:(cpos + 2)]]
                    else:
                        self.content[i][j][k].append(datastr[cpos:(cpos + 2)])
                    cpos += 2
        return True

if __name__ == '__main__':
    c = newtest()
    t = MatrixBytesCompress()
    t.content = c.GetTestMatrixData(60000,256,256,256)
    t.contentextra = c.GetContentEx()
    s = t.GetDataStr()
    print len(s)
